package com.yincheng.oms.bussiness.util.excel;

import static org.apache.commons.lang3.Validate.noNullElements;

import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor.HSSFColorPredefined;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;


public class ExcelExportUtils<T> {
	
	/**
	 * 将数据列表转换成excel对象
	 * @param clazz
	 * @param rows
	 * @throws IOException
	 */
	public ExcelExportUtils(Class<?> clazz, List<T> rows) throws IOException {
		List<ExcelTitleInfo> titles = new ArrayList<ExcelTitleInfo>();
		
		Field[] fields = clazz.getDeclaredFields();
		for (Field field : noNullElements(fields)) {
			ExcelFieldTitle efield = field.getAnnotation(ExcelFieldTitle.class);
			if (efield != null) {
				ExcelTitleInfo title = new ExcelTitleInfo();
				title.setTitle(efield.value());
				title.setWitdh(efield.width());
				if(efield.type().equals("list")) {
					this.listTypeValue = efield.value();
				}
				titles.add(title);
			}
		}
		
		
		this.wb               = new HSSFWorkbook();
		this.titleCellStyle   = createTitleCellStyle();
		this.contentCellStyle = createContentStyle();
		
		
		
		List<List<Object>> prows = new ArrayList<List<Object>>();
		try {
			prows = partition(rows);
		} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
			
		HSSFSheet sheet = wb.createSheet();
		
		
		try {
			setContexts(sheet, titles, prows);
		} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		List<String> titleNames = getTitleNames(titles);
		setTitle(sheet, titleNames);
		
		setSheetSizeColumn(0, titles, sheet);
	}
	
	protected List<List<Object>> partition(List<T> rows) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException{
		List<List<Object>> prows = new ArrayList<List<Object>>();
		for (T t : rows) {
			List<Object> objects = new ArrayList<Object>();
			Class<?> objClass = t.getClass();
			Field[] fields = objClass.getDeclaredFields();
			for (int i = 0; i < fields.length; i++) {
				Field f = objClass.getDeclaredField(fields[i].getName());
				f.setAccessible(true);
				ExcelFieldTitle annotation = f.getAnnotation(ExcelFieldTitle.class);
				if(annotation != null) {
					Object o = f.get(t);
					objects.add(o);
				}
			}
			prows.add(objects);
		}
		return prows;
	}
	
	private void setSheetSizeColumn(int rowIndex, List<ExcelTitleInfo> titles, HSSFSheet sheet) {

		int coloumNum=sheet.getRow(rowIndex).getPhysicalNumberOfCells();
		for(int i = 0;i<coloumNum;i++){
			ExcelTitleInfo lmr = titles.get(i);
			if(null == lmr || StringUtils.isEmpty(lmr.getWitdh())){
				int length = lmr.getWitdh().getBytes().length;
				sheet.setColumnWidth(i, length*256);
			}else {
				try{
					Integer width = Integer.parseInt(lmr.getWitdh());
					sheet.setColumnWidth(i, width*1000);
				}catch(Exception e){
					sheet.autoSizeColumn((short)i);
				}
			}
		}
		
	}

	protected List<String> getTitleNames(List<ExcelTitleInfo> titles) {
		List<String> list = new ArrayList<String>();
		for (ExcelTitleInfo title : titles) {
			list.add(title.getTitle());
		}
		return list;
	}
	
	protected void setContexts(HSSFSheet sheet, List<ExcelTitleInfo> titles, List<List<Object>> rows) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
		int i = 1;
		int t = 1;
		for (List<Object> row : rows) {
			HSSFRow frow = sheet.createRow(i);
			
			int j = 0;
			
			for (Object obj : row) {
				
				int m = 0;
				if(obj instanceof Date) {
					HSSFCell cell = frow.createCell(j);
					cell.setCellStyle(contentCellStyle);
					cell.setAsActiveCell();
					SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
					String value = sdf.format(obj);
					cell.setCellValue(value);
					j++;
				}else if(obj instanceof List) {
					@SuppressWarnings("unchecked")
					List<Object> subObjs = (List<Object>) obj;
					for (Object object : subObjs) {
						m++;
						HSSFCell cell = frow.createCell(j);
						cell.setCellStyle(contentCellStyle);
						cell.setAsActiveCell();
						String log = "";
						Class<?> objClazz = object.getClass();
						Field[] declaredFields = objClazz.getDeclaredFields();
						for (Field field : declaredFields) {
							Field declaredField = objClazz.getDeclaredField(field.getName());
							declaredField.setAccessible(true);
							ExcelFieldTitle annotation = declaredField.getAnnotation(ExcelFieldTitle.class);
							if(annotation != null) {
								Object v = declaredField.get(object);
								if(v instanceof Date) {
									SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
									v = sdf.format(v);
								}
								log = log + annotation.value()+ v + ";";
							}
							
						}
						cell.setCellValue(log);
						j++;
						
					}
					
					if (m > t)
						t = m;
				}else {
					HSSFCell cell = frow.createCell(j);
					cell.setCellStyle(contentCellStyle);
					cell.setAsActiveCell();
					String value = (String) obj;
					cell.setCellValue(value);
					j++;
				}
			}
			i++;
		}
		
		if(t >1) {
			ExcelTitleInfo eti = new ExcelTitleInfo();
			for (ExcelTitleInfo titleInfo : titles) {
				if(titleInfo.getTitle().equals(listTypeValue)) {
					eti = titleInfo;
					titleInfo.setTitle(listTypeValue + "1");
				}
					
			}
			for(int l=1; l<t;l++) {
				ExcelTitleInfo eti2 = new ExcelTitleInfo();
				eti2.setTitle(listTypeValue + (l + 1));
				eti2.setWitdh(eti.getWitdh());
				titles.add(eti2);
			}
		}
	}
	
	public void export(OutputStream os) throws IOException {
		wb.write(os);
		os.flush();
	}

	protected final static int SHEET_MAX_ROW = 60000;
	
	
	protected HSSFWorkbook wb;
	
	protected HSSFCellStyle titleCellStyle;
	
	protected HSSFCellStyle contentCellStyle;
	
	protected String listTypeValue;//成员变量类型为集合类型的注解的value值

	
	protected void setSheetAutoSizeColumn(int rowIndex,HSSFSheet sheet){
		int coloumNum=sheet.getRow(rowIndex).getPhysicalNumberOfCells();
		for(int i = 0;i<coloumNum;i++){
			sheet.autoSizeColumn((short)i); //调整列宽度
		}
	}
	
	protected void setTitle(HSSFSheet sheet, List<String> titleNames) {
		HSSFRow head = sheet.createRow(0);
		int i = 0;
		for (String titleName : titleNames) {
			HSSFCell cell = head.createCell(i);
			cell.setCellType(CellType.STRING);
			cell.setCellStyle(titleCellStyle);
			cell.setAsActiveCell();
			
			cell.setCellValue(titleName);
			
			i++;
		}
	}
	
	
	/**
	 * 创建每列的内容的样式
	 */
	protected  HSSFCellStyle createTitleCellStyle() {
		HSSFCellStyle style = wb.createCellStyle();
		
		style.setFillForegroundColor(HSSFColorPredefined.GREY_25_PERCENT.getIndex());// 设置填充背景为浅灰色
		// 设置边框样式
		style.setBorderBottom(BorderStyle.THIN);
		style.setBorderLeft(BorderStyle.THIN);
		style.setBorderRight(BorderStyle.THIN);
		style.setBorderTop(BorderStyle.THIN);
		
		style.setAlignment(HorizontalAlignment.LEFT); //居左
		
		style.setFont(createTitleFont());// 把字体应用到当前的样式
		
		return style;
	}

	/**
	 * 创建每列的内容的文字样式
	 */
	protected HSSFFont createTitleFont() {
		HSSFFont font = wb.createFont();
		font.setColor(HSSFColorPredefined.BLACK.getIndex());// 设置字体为黑色
		font.setBold(true);// 设置字体为加粗
		font.setFontHeightInPoints((short)12);// 设置字体大小为12号
		return font;
	}
	

	protected String getFieldValue(T t, String fieldName) {
		Field field = null;
		try {
			field = t.getClass().getDeclaredField(fieldName);
		} catch (NoSuchFieldException | SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		Object object = null;
		try {
			object = field.get(fieldName);
		} catch (IllegalArgumentException | IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		if(object instanceof Date){
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			return sdf.format(object);
		}
		return object == null ? "" : object.toString();
		
	}



	/**
	 * 设置每列的内容的样式
	 */
	private  HSSFCellStyle createContentStyle() {
		HSSFCellStyle style = wb.createCellStyle();
		style.setFillForegroundColor(HSSFColorPredefined.WHITE.getIndex());
		style.setFont(createContentFont());
		// 设置边框样式
		style.setBorderBottom(BorderStyle.THIN);
		style.setBorderLeft(BorderStyle.THIN);
		style.setBorderRight(BorderStyle.THIN);
		style.setBorderTop(BorderStyle.THIN);
		style.setAlignment(HorizontalAlignment.LEFT);
		return style;
	}

	/**
	 * 设置每列的内容的文字样式
	 */
	protected  HSSFFont createContentFont() {
		HSSFFont font = wb.createFont();
		Short st = 11;
		font.setColor(HSSFColorPredefined.BLACK.getIndex());
		font.setFontHeightInPoints(st);
		return font;
	}

}
